#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ncurses.h>
#include <menu.h>

#include "win_stdscr.h"
#include "win_menu.h"

#include "ec_read_write.h"

#if 1
int const_nMaxColumn()
{
	return (const_nMaxCell*3-2);
}
#endif




#if 1
typedef int (CB_READ_EC_DATA)(int nbase_addrpara,struct_cell_data* p_type_cell_data, chtype color);
typedef struct 
{
	unsigned char key[20];
	unsigned char menu[10];
	CB_READ_EC_DATA* pFuncReadEc;


}struct_win_stdscr;
#endif

//static int main_menu(int menu_num);
static void prtwcelldata(int nline,int ncol,char* strpara,bool blReverse);
static bool getcellyx(WINDOW* win, int* nline, int* ncol, int* npos);

static bool editcellyx(WINDOW* win, int ch, struct_cell_data* type_cell_data,int menu_num, int nbase_addrpara);

static bool selectcellyx(WINDOW* win, int ch, struct_cell_data* type_cell_data);
static bool valid_first_cellyx(WINDOW* win, struct_cell_data* type_cell_data);


static bool goto_first_cellyx(WINDOW* win, struct_cell_data* type_cell_data)
{

	int nline=0,ncol=0;
	//int npos;

	//if(false==getcellyx(win, &nline, &ncol, &npos))
	//	return false;

	prtwcelldata(nline, ncol,(char*)&type_cell_data->data_cell[nline][ncol],true);


	return true;

}


static bool selectcellyx(WINDOW* win, int ch, struct_cell_data* type_cell_data)
{
#if 1
	int nline,ncol;
	int npos;

	if(false==getcellyx(win, &nline, &ncol, &npos))
		return false;

	prtwcelldata(nline, ncol,(char*)&type_cell_data->data_cell[nline][ncol],false);


	switch(ch)
	{
		case KEY_LEFT:
		{
			ncol--;
			if(ncol<0)
				ncol=0;
			break;
		}

		case KEY_RIGHT:
		{
			ncol++;
			if(ncol>=const_nMaxCell)
				ncol=const_nMaxCell-1;
			break;
		}

		case KEY_UP:
		{
			nline--;
			if(nline<0)
				nline=0;
			break;
		}

		case KEY_DOWN:
		{
			nline++;
			if(nline>=const_nMaxLine)
				nline=const_nMaxLine-1;

			break;
		}

	}
#endif

	prtwcelldata(nline, ncol,(char*)&type_cell_data->data_cell[nline][ncol],true);

	return true;

}


//unsigned char data_cell[const_nMaxLine][const_nMaxCell][3];

bool editcellyx(WINDOW* win, int ch, struct_cell_data* type_cell_data,int menu_num, int nbase_addrpara)
{
	int x,y;
	int nline,ncol;
	int npos;

	if(false==getcellyx(win, &nline, &ncol, &npos))
		return false;

	//if(x<defnColBgn+const_nMaxColumn()+1)
	{
		attron(A_REVERSE);
		type_cell_data->data_cell[nline][ncol][npos]=ch;
		printw("%c", type_cell_data->data_cell[nline][ncol][npos]);
		attroff(A_REVERSE);
		if(npos==1)
		{
			#if 1
			
			int nval = strtol((const char*)type_cell_data->data_cell[nline][ncol], NULL, 16);

			wattron(stdscr, COLOR_PAIR(1));
			//mvprintw(LINES - 3, 0, "menu_num =%d defKeyFMenuBgn+4 %d nline %02X ncol %02X write data %02X \n",menu_num,defKeyFMenuBgn+4,nline,ncol,nval);
			
			char strtmp[64];
			memset(strtmp,' ',sizeof(strtmp)-1);
			strtmp[sizeof(strtmp)-1]=0x00;
			mvprintw(defnLineBgn + const_nMaxLine +4, defnColBgn, " %s ", strtmp);
			mvprintw(defnLineBgn + const_nMaxLine +4, defnColBgn, "write data %02X ", nval);


			int Index;

			if(menu_num >= defKeyFMenuBgn  && menu_num <= defKeyFMenuBgn+3 )
			{
				Index = nbase_addrpara+nline*const_nMaxCell+ncol;
				ecio_write_byte(Index, nval);
				nval=0xFF;
				usleep(100*1000);
				nval=ecio_read_byte(Index);

			}
			else if(menu_num == defKeyFMenuBgn+4 )
			{
				Index = (nbase_addrpara<<8)+nline*const_nMaxCell+ncol;
				pnp_write_byte(Index, nval);
				//mvprintw(LINES - 5, 0, "Index %04X read data %02X \n",Index,nval);
				nval=0xFF;
				usleep(100*1000);
				//sleep(3);
				nval=pnp_read_byte(Index)&0xFF;

				//mvprintw(LINES - 6, 0, "Index %04X read data %02X \n",Index,nval);

			}

			mvprintw(defnLineBgn + const_nMaxLine +5, defnColBgn, " %s ", strtmp);
			mvprintw(defnLineBgn + const_nMaxLine +5, defnColBgn, "read data %02X ", nval&0x0FF);
			//mvprintw(LINES - 7, 0, "nline %02X ncol %02X read data %02X \n",nline,ncol,nval);


			wattroff(stdscr, COLOR_PAIR(1));
			#endif

			char str[25];
			sprintf(str,"%02X ", nval );
		
			memcpy(&type_cell_data->data_cell[nline][ncol],str,2);

			prtwcelldata(nline, ncol,(char*)&type_cell_data->data_cell[nline][ncol],true);

			move(nline+defnLineBgn, defnColBgn+ncol*3);
		}
	}
	return true;

}

bool getcellyx(WINDOW* win, int* nline, int* ncol, int* npos)
{
	int x, y;
	getyx(win, y, x);

	if(x<defnColBgn)
		return false;
	if(x>defnColBgn+const_nMaxColumn()+1)
		return false;

	if(y<defnLineBgn)
		return false;
	if(y>=defnLineBgn+const_nMaxLine)
		return false;

	*nline=y-defnLineBgn;
	*ncol=(x-defnColBgn)/3;
	*npos=(x-defnColBgn)%3;

	return true;
}

void prtwcelldata(int nline,int ncol,char* strpara,bool blReverse)
{
	char str[25];
			//itoa(i, str, 16);
	str[0]=strpara[0];
	str[1]=strpara[1];
	str[2]=0;

	//sprintf(str,"%s",data_cell[nline][ncol]);
	move(nline+defnLineBgn,ncol*3+defnColBgn);
	if(blReverse)
		attron(A_REVERSE);
	else attroff(A_REVERSE);
	printw(str);
	move(nline+defnLineBgn,ncol*3+defnColBgn);
}

void prtwcell_toptitle()
{

	//sprintf(str,"%s",data_cell[nline][ncol]);

	start_color();
	init_pair(1, COLOR_RED, COLOR_BLACK);
	init_pair(2, COLOR_CYAN, COLOR_BLACK);

	attron(COLOR_PAIR(2));
	
	int ncol;
	//attron(A_REVERSE);
	for(ncol=0;ncol<const_nMaxCell;ncol++)
	{
		char str[25];
				//itoa(i, str, 16);
		//str[2]=0;
		sprintf(str,"%02X ",ncol);

		move(defnLineBgn-1,ncol*3+defnColBgn);	
		printw(str);
	}
	

	int nline;

	for(nline=0;nline<const_nMaxLine;nline++)
	{
		char str[25];
				//itoa(i, str, 16);
		//str[2]=0;
		sprintf(str,"%1X0h ",nline);

		move(defnLineBgn+nline,defnColBgn-4);	
		printw(str);
	}

	attroff(COLOR_PAIR(2));
	

	//attroff(A_REVERSE);

}


void init_cell(struct_cell_data* p_type_cell_data, int nVal)
{
	prtwcell_toptitle();
	int nline, ncol;
    for(nline=0;nline<const_nMaxLine;nline++)
    {
    	for(ncol=0;ncol<const_nMaxCell;ncol++)
		{
			char str[25];
			//itoa(i, str, 16);
			//sprintf(str,"%02X",nline*const_nMaxCell+ncol);
			sprintf(str,"%02X ",nVal);
			
			memcpy(p_type_cell_data->data_cell[nline][ncol],str,2);
		}
	}

    for(nline=0;nline<const_nMaxLine;nline++)
    {
    	for(ncol=0;ncol<const_nMaxCell;ncol++)
		{
	    	prtwcelldata(nline, ncol,(char*)&p_type_cell_data->data_cell[nline][ncol],false);
		}
	}
}

void prt_cell_by_alldata(struct_cell_data type_cell_data)
{
	//prtwcell_toptitle();
	int nline, ncol;

    for(nline=0;nline<const_nMaxLine;nline++)
    {
    	for(ncol=0;ncol<const_nMaxCell;ncol++)
		{
	    	prtwcelldata(nline, ncol,(char*)&type_cell_data.data_cell[nline][ncol],false);
		}
	}
}


int win_stdcr(int para_num)
{	int ch;

	initscr();			/* Start curses mode 		*/
	raw();				/* Line buffering disabled	*/
	keypad(stdscr, TRUE);		/* We get F1, F2 etc..		*/
	noecho();			/* Don't echo() while we do getch */

    //printw("Type any character to see it in bold\n");
	int y, x;
    int nline, ncol;
    int addr;

	struct_cell_data type_cell_data;
	init_cell(&type_cell_data,0x0FF);


	const struct_win_stdscr type_main_menu[]=
	{
		{
			"(F2)", "EC_REGA",read_ECIO_RAM,
		},
		{
			"(F3)", "EC_REGB",read_ECIO_RAM,
		},
		{
			"(F4)", "EC_RAM",read_ECIO_RAM,
		},
		{
			"(F5)", "EC_DLM",read_ECIO_RAM,
		},
		{
			"(F6)", "PNPCFG",read_PNPCFG,
		},

		{
			"(F7)", "Other",NULL,
		},
		{
			"(F8)", "EDIT",
		},
		{
			"(F9)", "Quit",
		}

	};



	for(nline=0;nline<sizeof(type_main_menu)/sizeof(struct_win_stdscr);nline++)
	{
		char str[10];
		sprintf(str,"F%d",nline+2);
		mvprintw(0,defnMainMenuColBgn+nline*10,(const char*)str);
		//mvprintw(0,defnColBgn+nline*10,(const char*)type_main_menu[nline].key);
		mvprintw(1,defnMainMenuColBgn+nline*10,(const char*)type_main_menu[nline].menu);
	}

    bool blrunning=true;
    attroff(A_BLINK);
    
    int menu_num=0;
    while(blrunning)
    {
		ch = getch();			/* If raw() hadn't been called
						 * we have to press enter before it
						 * gets to the program 		*/
		//if(ch == defKeyFMenuBgn+6 )		/* Without keypad enabled this will */
		//	printw("F7 Key pressed");/*  not get to us either	*/
						/* Without noecho() some ugly escape
						 * charachters might have been printed
						 * on screen			*/

		if(ch >= defKeyFMenuBgn  && ch <= defKeyFMenuBgn+5 )
		{
			menu_num=ch;
			bool blmenu_choise=true;
			while(blmenu_choise==true)
			{
				
				keypad(stdscr, FALSE);
				int n_menu_ret_num;
	    		n_menu_ret_num=win_menu(menu_num,(const char*)type_main_menu[menu_num-defKeyFMenuBgn].menu,&addr);


	    		keypad(stdscr, TRUE);
				//update_panels();
				//doupdate();
				touchwin(stdscr);
			    refresh();

			    //mvprintw(LINES - 4, 0, "Arrow Keys to navigate (F1 to Exit) menu_num %d",menu_num);
	    		//menu_num=0;
	    		if(n_menu_ret_num >= defKeyFMenuBgn  && n_menu_ret_num <= defKeyFMenuBgn+5 )
	    		{
	    			menu_num=n_menu_ret_num;
	    			blmenu_choise=true;
	    		}
	    		else
	    		{
	    			blmenu_choise=false;

	    			if(type_main_menu[menu_num-defKeyFMenuBgn].pFuncReadEc!=NULL)
	    			{
	    				type_main_menu[menu_num-defKeyFMenuBgn].pFuncReadEc(addr,&type_cell_data,COLOR_PAIR(1));
	    				prt_cell_by_alldata(type_cell_data);
	    			}

	    		}

			}
			
		}

		#if 0
		else if(ch == KEY_F(3))
		{
			menu_num=3;
    		win_menu(menu_num);
    		menu_num=0;
		}
		#endif

	    else if(ch == defKeyFMenuExit )
	    	blrunning=false;
	    else if(ch == defKeyFMenuEntryEdit )
	    //else if(ch == KEY_F(8) )
	    {
	    	goto_first_cellyx(stdscr,&type_cell_data);	
	    }
		else if( 
			(ch >='0' && ch<='9')||
			(ch >='a' && ch<='f')||
			(ch >='A' && ch<='F')
			)
		{	//printw("The pressed key is ");
			if(ch >='a' && ch<='f')
				ch=ch-32;

			int npos;
			editcellyx(stdscr, ch, &type_cell_data,menu_num,addr);

		}
		else if( ch==KEY_LEFT || ch==KEY_RIGHT || ch==KEY_UP || ch==KEY_DOWN )
		{
			selectcellyx(stdscr,ch,&type_cell_data);


		}
		else
		{
			//gityx(stdscr,);
			//move(20,0);
		}

		refresh();			/* Print it on to the real screen */
		
	}

    //getch();			/* Wait for user input */
	endwin();			/* End curses mode		  */

	return 0;
}



